package com.lxw.station.components;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lxw.station.api.CSDNApi;
import com.lxw.station.config.CSDNData;
import com.lxw.station.constant.CSDNConstant;
import com.lxw.station.dto.RankContent;
import com.lxw.station.dto.csdn.CsdnFollow;
import com.lxw.station.dto.csdn.UserCookieDTO;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Component
@Slf4j
public class CsdnService {
    @Resource
    RedisTemplate<String, Object> redisTemplate;

    /**
     * 更新我的关注
     */
    public void updateFollows() {
        for (UserCookieDTO userCookieDTO : CSDNApi.getUserCookieDTOs()) {
            long start = System.currentTimeMillis();
            String userName = userCookieDTO.getUserName();
            String cookie = userCookieDTO.getCookie();
            List<CsdnFollow> follows = CSDNApi.getFollowsFromCSDN(cookie, userName);
            if (CollectionUtils.isEmpty(follows)) {
                continue;
            }
            // 保存原始json数据
            redisTemplate.delete(CSDNConstant.CSDN_FOLLOWS +userName);
            redisTemplate.opsForValue().set(CSDNConstant.CSDN_FOLLOWS +userName, follows);
            // 保存用户名
            redisTemplate.delete(CSDNConstant.CSDN_FOLLOWS_USERNAME +userName);
            redisTemplate.opsForSet().add(CSDNConstant.CSDN_FOLLOWS_USERNAME +userName, follows.stream().map(CsdnFollow::getUsername).toArray());
            long end = System.currentTimeMillis();
            log.info("获取 {} 关注的总人数:{},耗时:{}秒",userName, follows.size(), (end - start) / 1000);
        }
    }


    /**
     * 关注点赞评论
     */
    @SneakyThrows
    public void followLikeComment() {
        for (UserCookieDTO userCookieDTO : CSDNApi.getUserCookieDTOs()) {
            try {
                followLikeComment(userCookieDTO.getUserName(), userCookieDTO.getCookie());
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }

    }

    /**
     * 关注点赞评论
     * @param userName 当前登录用户
     * @param cookie   当前登录用户的cookie
     */
    @SneakyThrows
    public void followLikeComment(String userName, String cookie) {
        SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
        // 所有用户关注的人
        Set<Object> allFollowUserNames = new HashSet<>();
        // weixin_41883161 关注的人
        allFollowUserNames.addAll(setOperations.members(CSDNConstant.CSDN_FOLLOWS_USERNAME+ CSDNConstant.MY_USERNAME));
        allFollowUserNames.addAll(setOperations.members(CSDNConstant.CSDN_FOLLOWS_USERNAME+ "baidu_16992441"));
        allFollowUserNames.addAll(setOperations.members(CSDNConstant.CSDN_FOLLOWS_USERNAME+ "kaoshenfutipxzx"));
        allFollowUserNames.addAll(setOperations.members(CSDNConstant.CSDN_FOLLOWS_USERNAME+ "wlgcsczbj"));

        // 内容榜所有文章
        List<RankContent> allRankContents = getAllRankContents();
        // 待关注的人
        List<RankContent> willFolloweds = new ArrayList<>();
        for (Map.Entry<String, List<RankContent>> entry : allRankContents.stream().collect(Collectors.groupingBy(RankContent::getUserName)).entrySet()) {
            if (!allFollowUserNames.contains(entry.getKey())) {
                willFolloweds.add(entry.getValue().get(0));
            }
        }
        log.info("从领域内容排行榜中获取到的我未关注的人数:{}", willFolloweds.size());
        for (RankContent rankContent : willFolloweds) {
            String follow = CSDNApi.follow(userName, rankContent.getUserName(), cookie);
            if (follow.contains("已关注")) {
                continue;
            }
            setOperations.add(CSDNConstant.CSDN_FOLLOWS_USERNAME+ userName,rankContent.getUserName());
            log.info("{}将要 点赞评价 标题:{},链接:{}", userName,rankContent.getArticleTitle(), rankContent.getArticleDetailUrl());
            Thread.sleep(3000);
            CSDNApi.like(rankContent.getProductId(), cookie);
            Thread.sleep(3000);
            CSDNApi.comment(rankContent.getProductId(), userName, cookie);
            Thread.sleep(60000);
        }
    }

    /**
     * 获取所有的内容榜
     */
    private List<RankContent> getAllRankContents() {
        List<RankContent> rankContents = new ArrayList<>();
        ValueOperations<String, Object> operations = redisTemplate.opsForValue();
        for (String childChannel : CSDNData.childChannels) {
            rankContents.addAll(((JSONArray) operations.get("csdn:rank:content:" + childChannel)).toJavaList(RankContent.class));
        }
        return rankContents;
    }

    public void unFollows() {
        String myFollowsKey = "csdn:follows:lxw";
        ValueOperations<String, Object> operations = redisTemplate.opsForValue();
        JSONArray jsonArray = (JSONArray) operations.get(myFollowsKey);
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(jsonArray.size() - i - 1);
            if ("1".equals(jsonObject.getString("relation"))) {
                String username = jsonObject.getString("username");
                String nickname = jsonObject.getString("nickname");
                if (!CSDNApi.unFollow(username)) {
                    log.info("取消关注:{}失败", nickname);
                    return;
                }
                log.info("取消关注:{}成功", nickname);
            }
        }
    }
    public void updateContentRank() {
        log.info("开始更新领域内容榜");
        List<String> childChannels = CSDNData.childChannels;
        for (String childChannel : childChannels) {
            JSONArray contentRank = CSDNApi.getContentRank(childChannel);
            redisTemplate.opsForValue().set(CSDNData.RANK_CONTENT + childChannel, contentRank);
        }
    }
}
